﻿//----------------------------------------------------------------
// Copyright (c) 2011-2013 
// All rights reserved.
// Author: Ben DaoWei 
// Contact: bendaowei@gmail.com
// Web Link: http://xnaeditor.codeplex.com
// ----------------------------------------------------------------


namespace UnityEngine.Core
{
    using Microsoft.Xna.Framework;
    using System.Xml.Serialization;
    using System.Xml.Schema;
    using System.Xml;
    using System.IO;
    using System;
    using UnityEngine.IO;
    using System.Reflection;
    using System.Collections.Generic;

    public class Component
    {
        protected XmlNode _XmlNode;

        public delegate void ComponentEventHandler(GameTime time);

        public Component()
            : this(null)
        {
        }

        public Component(GameObject gameObject)
        {
            this.GameObject = gameObject;
        }

        public GameObject GameObject { get; set; }

        public virtual void Startup(GameTime gameTime)
        {
        }

        public virtual void Draw(GameTime gameTime)
        {
        }

        public virtual void Update(GameTime gameTime)
        {
        }

        public virtual void Destroy(GameTime gameTime)
        {
        }

        public virtual void UpdatePhysics(GameTime gameTime)
        {
        }

        public void RemoveSelfFromGameObject()
        {
            this.GameObject.RemoveComponent(this.GetType().Name);
        }

        public virtual XmlSchema GetSchema()
        {
            return null;
        }

        public virtual void ReadXml(XmlNode root)
        {
            // record xml node
            this._XmlNode = root;

            Dictionary<string, XmlNode> children = new Dictionary<string, XmlNode>();
            for (int i = 0; i < root.ChildNodes.Count; i++)
                children.Add(root.ChildNodes[i].Name, root.ChildNodes[i]);

            Serializer serializer = new Serializer();

            PropertyInfo[] properties =
                this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            for (int i = 0; i < properties.Length; i++)
            {
                PropertyInfo info = properties[i];
                if (info.CanWrite == false ||
                    info.CanRead == false)
                    continue;
                if (info.GetCustomAttributes(typeof(EditableAttribute), false).Length > 0)
                {
                    if (children.ContainsKey(info.Name) == true)
                    {
                        object value = serializer.Deserialize(info.Name, children[info.Name], info.PropertyType);
                        if (value != null)
                            info.SetValue(this, value, null);
                    }
                }
            }
        }

        public virtual void WriteXml(XmlWriter writer)
        {
            Serializer serializer = new Serializer();

            PropertyInfo[] properties =
                this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            for (int i = 0; i < properties.Length; i++)
            {
                PropertyInfo info = properties[i];
                if (info.CanWrite == false ||
                    info.CanRead == false)
                    continue;
                if (info.GetCustomAttributes(typeof(EditableAttribute), false).Length > 0)
                {
                    serializer.Serialize(info.Name, info.GetValue(this, null), writer, info.PropertyType);
                }
            }
        }

        public virtual int Priority
        {
            get
            {
                return 0;
            }
        }
    }
}
